package com.anjufang.common.exception;

import com.anjufang.utils.Result;
import com.anjufang.utils.StringUtils;
import org.apache.shiro.authz.AuthorizationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MultipartException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;

/**
 * 异常处理器
 * 
 * @author chenshun
 * @email sunlightcs@gmail.com
 * @date 2016年10月27日 下午10:16:19
 */
@RestControllerAdvice
public class PHExceptionHandler {
	private Logger logger = LoggerFactory.getLogger(getClass());

	/**
	 * 自定义异常
	 */
	@ExceptionHandler(PHException.class)
	public Result handleRRException(PHException e) {
		Result r = new Result();
		r.put("code", e.getCode());
		r.put("msg", e.getMessage());

		return r;
	}

	@ExceptionHandler(DuplicateKeyException.class)
	public Result handleDuplicateKeyException(DuplicateKeyException e) {
		logger.error(e.getMessage(), e);
		return Result.error("数据库中已存在该记录");
	}

	@ExceptionHandler(AuthorizationException.class)
	public Result handleAuthorizationException(AuthorizationException e) {
		logger.error(e.getMessage(), e);
		return Result.error("没有权限，请联系管理员授权");
	}

	/**
	 * 上传图片过大异常捕获
	 * 
	 * @param e
	 * @return
	 */
	@ExceptionHandler(MultipartException.class)
	public Result handleMultipartException(Exception e) {
		logger.error(e.getMessage(), e);
		return Result.error("图片大小过大，请更换新的图片!");
	}

	/**
	 * MQ队列未开启异常捕获
	 * 
	 * @param e
	 * @return
	 */
	/*@ExceptionHandler(UncategorizedJmsException.class)
	public Result handleJMSException(UncategorizedJmsException e) {
		logger.error(e.getMessage(), e);
		return Result.error("请联系管理员开启MQ");
	}*/

	/**
	 * 处理Redis没开启的异常
	 * 
	 * @param e
	 * @return
	 */
	/*@ExceptionHandler(JedisException.class)
	public Result redisHandle(JedisException e) {
		logger.error("Redis 缓存异常,异常名:" + e.getMessage());
		return Result.error("缓存未开启,请联系管理员开启!");
	}*/

	/**
	 * Hibernate Validator参数校验异常处理
	 * @param e
	 * @return
	 */
	@ExceptionHandler(MethodArgumentNotValidException.class)
	public Result handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
		System.out.println("Hibernate Validator参数校验异常处理");
		BindingResult bindingResult = e.getBindingResult();
        ObjectError objectError = bindingResult.getAllErrors().get(0);
        String msg = objectError.getDefaultMessage();
        System.out.println(msg);
		return Result.error(msg);
	}
	
	/**
     * Spring Validator参数校验异常处理
     * @param e
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public Result handler(ConstraintViolationException e) {
    	System.out.println("Spring Validator参数校验异常处理");
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        for (ConstraintViolation<?> constraintViolation : constraintViolations) {
            String message = constraintViolation.getMessage();
            if (!StringUtils.isEmpty(message)) {
                //直接返回第一个错误信息
            	return Result.error(message);
            }
        }
        return Result.error();
    }
	
    /**
	 * Validator 参数校验异常处理
	 * @param ex
	 * @return
	 */
	@ExceptionHandler(value = BindException.class)
	public Result handleMethodVoArgumentNotValidException(BindException ex) {
		FieldError err = ex.getFieldError();
		// err.getField() 读取参数字段
		// err.getDefaultMessage() 读取验证注解中的message值
		String message = "参数{".concat(err.getField()).concat("}").concat(err.getDefaultMessage());
		//logger.info("{} -> {}", err.getObjectName(), message);
		System.out.println(message);
		//return new ResponseEntity<Object>(new ResultVO(ResultCode.PARAM_INVALID, message), HttpStatus.OK);
		return Result.error(message);
	}
    
	/**
	 * 表单数据校验
	 * 
	 * @param e
	 * @return
	 */
	/*@ExceptionHandler(ClientException.class)
	public Result handleClientException(ClientException e) {
		return Result.error("获取验证码失败！");
	}*/

	@ExceptionHandler(Exception.class)
	public Result handleException(Exception e) {
		logger.error(e.getMessage(), e);
		return Result.error();
	}

}
